package silvercrux.cmm;

import com.sun.org.apache.xpath.internal.operations.Bool;
import silvercrux.runtime.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by SilverCrux on 2016/12/6.
 */
public class SCCVisitor extends cmmBaseVisitor<Object> {

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitProg(cmmParser.ProgContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitPrimaryExpression(cmmParser.PrimaryExpressionContext ctx) {
        if (ctx.expression() != null) return visit(ctx.getChild(1));
        if (ctx.Constant() != null) {
            PushConstant(ctx.Constant().getText());
            return null;
        }
        if (ctx.Identifier() != null) {
            if (RuntimeVirtualMachine.getIdMap().containsKey(ctx.Identifier().getText())) {
                RuntimeVirtualMachine.getrStack().push(RuntimeVirtualMachine.getIdMap().get(ctx.Identifier().getText()));
                //System.out.println(RuntimeVirtualMachine.getIdMap().get(ctx.Identifier().getText()).getClass().toString());
                return null;
            } else {
                ErrorOutput.Error("未声明的变量:" + ctx.Identifier().getText() + "    行号:" + ctx.Identifier().getSymbol().getLine());
            }
            return null;
        }
        if (ctx.Zero() != null) {
            RuntimeVirtualMachine.getrStack().push(new Integer(0));
            return null;
        }
        return null;
    }

    private void PushConstant(String constant) {
        if (constant.contains(".")) {
            RuntimeVirtualMachine.getrStack().push(Float.valueOf(constant));
            return;
        }
        RuntimeVirtualMachine.getrStack().push(Integer.valueOf(constant));
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitPostfixExpression(cmmParser.PostfixExpressionContext ctx) {
        if (ctx.getChildCount() == 1) {
            return visitChildren(ctx);
        }
        visit(ctx.postfixExpression());
        Object tmp = RuntimeVirtualMachine.getrStack().pop();
        if (ctx.getChild(1).getText().equals("[")) {
            //(tmp.getClass());
            if (tmp.getClass().toString().equals(Array.class.toString())) {
                int num;
                if (ctx.expression() != null) {
                    visit(ctx.expression());
                    Object res = RuntimeVirtualMachine.getrStack().pop();
                    if(res.getClass().equals(Var.class)&&((Var)res).type.equals("Integer"))
                    {
                        res = ((Var)res).value;
                    }
                    if(!res.getClass().equals(Integer.class))
                    {
                        ErrorOutput.Error("数组下标类型有误    行号:"+ctx.getStart().getLine());
                    }
                    num = (Integer)res;
                } else num = Integer.valueOf(ctx.getChild(2).getText());
                RuntimeVirtualMachine.getrStack().push(((Array) tmp).array[num]);
            } else {
                ErrorOutput.Error("该对象并非数组    行号:" + ctx.getStart().getLine());
            }
        }
        return null;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitArgumentExpressionList(cmmParser.ArgumentExpressionListContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitUnaryExpression(cmmParser.UnaryExpressionContext ctx) {
        if (ctx.getChildCount() == 1) {
            return visitChildren(ctx);
        }
        return null;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitMultiplicativeExpression(cmmParser.MultiplicativeExpressionContext ctx) {
        if (ctx.getChildCount() == 1) return visitChildren(ctx);
        visit(ctx.getChild(0));
        String op = ctx.getChild(1).getText();
        visit(ctx.getChild(2));
        Object i;
        Object second = RuntimeVirtualMachine.getrStack().pop();
        Object first = RuntimeVirtualMachine.getrStack().pop();
        switch (op) {
            case "*":
                i = Mult(first, second);
                RuntimeVirtualMachine.getrStack().push(i);
                break;
            case "/":
                i = Div(first, second);
                RuntimeVirtualMachine.getrStack().push(i);
                break;
            default:
        }
        return null;
    }

    private Object Mult(Object first, Object second) {
        if (first.getClass().equals(Var.class)) {
            first = ((Var) first).value;
        }
        if (second.getClass().equals(Var.class)) {
            second = ((Var) second).value;
        }
        if (first.getClass().equals(Double.class) || second.getClass().equals(Double.class)) {
            return (Double.valueOf(first.toString()).doubleValue()) * (Double.valueOf(second.toString()).doubleValue());
        }
        if (first.getClass().equals(Float.class) || second.getClass().equals(Float.class)) {
            return (Float.valueOf(first.toString()).floatValue()) * (Float.valueOf(second.toString()).floatValue());
        }
        return (Integer.valueOf(first.toString()).intValue()) * (Integer.valueOf(second.toString()).intValue());
    }

    private Object Div(Object first, Object second) {
        if (first.getClass().equals(Var.class)) {
            first = ((Var) first).value;
        }
        if (second.getClass().equals(Var.class)) {
            second = ((Var) second).value;
        }
        if (first.getClass().equals(Double.class) || second.getClass().equals(Double.class)) {
            return (Double.valueOf(first.toString()).doubleValue()) / (Double.valueOf(second.toString()).doubleValue());
        }
        if (first.getClass().equals(Float.class) || second.getClass().equals(Float.class)) {
            return (Float.valueOf(first.toString()).floatValue()) / (Float.valueOf(second.toString()).floatValue());
        }
        return (Integer.valueOf(first.toString()).intValue()) / (Integer.valueOf(second.toString()).intValue());
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitCastExpression(cmmParser.CastExpressionContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitAdditiveExpression(cmmParser.AdditiveExpressionContext ctx) {
        if (ctx.getChildCount() == 1) return visitChildren(ctx);
        visit(ctx.getChild(0));
        String op = ctx.getChild(1).getText();
        visit(ctx.getChild(2));
        Object i;
        Object second = RuntimeVirtualMachine.getrStack().pop();
        Object first = RuntimeVirtualMachine.getrStack().pop();
        switch (op) {
            case "+":
                i = Add(first, second);
                RuntimeVirtualMachine.getrStack().push(i);
                break;
            case "-":
                i = Sub(first, second);
                RuntimeVirtualMachine.getrStack().push(i);
                break;
            default:
        }
        return null;
    }


    private Object Add(Object first, Object second) {
        if (first.getClass().equals(Var.class)) {
            first = ((Var) first).value;
        }
        if (second.getClass().equals(Var.class)) {
            second = ((Var) second).value;
        }
        if (first.getClass().equals(Double.class) || second.getClass().equals(Double.class)) {
            return (Double.valueOf(first.toString()).doubleValue()) + (Double.valueOf(second.toString()).doubleValue());
        }
        if (first.getClass().equals(Float.class) || second.getClass().equals(Float.class)) {
            return (Float.valueOf(first.toString()).floatValue()) + (Float.valueOf(second.toString()).floatValue());
        }
        return (Integer.valueOf(first.toString()).intValue()) + (Integer.valueOf(second.toString()).intValue());
    }

    private Object Sub(Object first, Object second) {
        if (first.getClass().equals(Var.class)) {
            first = ((Var) first).value;
        }
        if (second.getClass().equals(Var.class)) {
            second = ((Var) second).value;
        }
        if (first.getClass().equals(Double.class) || second.getClass().equals(Double.class)) {
            return (Double.valueOf(first.toString()).doubleValue()) - (Double.valueOf(second.toString()).doubleValue());
        }
        if (first.getClass().equals(Float.class) || second.getClass().equals(Float.class)) {
            return (Float.valueOf(first.toString()).floatValue()) - (Float.valueOf(second.toString()).floatValue());
        }
        return (Integer.valueOf(first.toString()).intValue()) - (Integer.valueOf(second.toString()).intValue());
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitShiftExpression(cmmParser.ShiftExpressionContext ctx) {
        if (ctx.getChildCount() == 1) return visitChildren(ctx);
        return null;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitRelationalExpression(cmmParser.RelationalExpressionContext ctx) {
        if (ctx.getChildCount() == 1) return visitChildren(ctx);
        visit(ctx.getChild(0));
        visit(ctx.getChild(2));
        String op = ctx.getChild(1).getText();
        Object second = RuntimeVirtualMachine.getrStack().pop();
        Object first = RuntimeVirtualMachine.getrStack().pop();
        switch (op) {
            case ">":
                RuntimeVirtualMachine.getrStack().push((Bigger(first, second)) ? 1 : 0);
                break;
            case "<":
                RuntimeVirtualMachine.getrStack().push((Smaller(first, second)) ? 1 : 0);
                break;
            case "<=":
                RuntimeVirtualMachine.getrStack().push((Smaller(first, second) && Equal(first, second)) ? 1 : 0);
                break;
            case ">=":
                RuntimeVirtualMachine.getrStack().push((Bigger(first, second) && Equal(first, second)) ? 1 : 0);
        }
        return null;
    }

    private Boolean Bigger(Object first, Object second) {
        if (first.getClass().equals(Var.class)) {
            first = ((Var) first).value;
        }
        if (second.getClass().equals(Var.class)) {
            second = ((Var) second).value;
        }
        if (first.getClass().equals(Double.class) || second.getClass().equals(Double.class)) {
            return (Double.valueOf(first.toString())).compareTo((Double.valueOf(second.toString())))>0?true:false;
        }
        if (first.getClass().equals(Float.class) || second.getClass().equals(Float.class)) {
            return (Float.valueOf(first.toString())).compareTo((Float.valueOf(second.toString())))>0?true:false;
        }
        return (Integer.valueOf(first.toString())).compareTo((Integer.valueOf(second.toString())))>0?true:false;
    }

    private Boolean Smaller(Object first, Object second) {
        if (first.getClass().equals(Var.class)) {
            first = ((Var) first).value;
        }
        if (second.getClass().equals(Var.class)) {
            second = ((Var) second).value;
        }
        if (first.getClass().equals(Double.class) || second.getClass().equals(Double.class)) {
            return (Double.valueOf(first.toString())).compareTo((Double.valueOf(second.toString())))<0?true:false;
        }
        if (first.getClass().equals(Float.class) || second.getClass().equals(Float.class)) {
            return (Float.valueOf(first.toString())).compareTo((Float.valueOf(second.toString())))<0?true:false;
        }
        return (Integer.valueOf(first.toString())).compareTo((Integer.valueOf(second.toString())))<0?true:false;
    }

    private Boolean Equal(Object first, Object second) {
        if (first.getClass().equals(Var.class)) {
            first = ((Var) first).value;
        }
        if (second.getClass().equals(Var.class)) {
            second = ((Var) second).value;
        }
        if (first.getClass().equals(Double.class) || second.getClass().equals(Double.class)) {
            return (Double.valueOf(first.toString())).equals(Double.valueOf(second.toString()));
        }
        if (first.getClass().equals(Float.class) || second.getClass().equals(Float.class)) {
            return (Float.valueOf(first.toString())).equals(Float.valueOf(second.toString()));
        }
        return (Integer.valueOf(first.toString())).equals(Integer.valueOf(second.toString()));
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitEqualityExpression(cmmParser.EqualityExpressionContext ctx) {
        if (ctx.getChildCount() == 1) return visitChildren(ctx);
        visit(ctx.getChild(0));
        visit(ctx.getChild(2));
        String op = ctx.getChild(1).getText();
        Object second = RuntimeVirtualMachine.getrStack().pop();
        Object first = RuntimeVirtualMachine.getrStack().pop();
        switch (op) {
            case "==":
                RuntimeVirtualMachine.getrStack().push((Equal(first, second)) ? 1 : 0);
                break;
            case "!=":
                RuntimeVirtualMachine.getrStack().push((Equal(first, second)) ? 0 : 1);
        }
        return null;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitAndExpression(cmmParser.AndExpressionContext ctx) {
        if (ctx.getChildCount() == 1) return visitChildren(ctx);
        visit(ctx.getChild(0));
        String op = ctx.getChild(1).getText();
        visit(ctx.getChild(2));
        Integer i = (Integer) RuntimeVirtualMachine.getrStack().pop() & (Integer) RuntimeVirtualMachine.getrStack().pop();
        RuntimeVirtualMachine.getrStack().push(i);
        return null;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitExclusiveOrExpression(cmmParser.ExclusiveOrExpressionContext ctx) {
        if (ctx.getChildCount() == 1) return visitChildren(ctx);
        return null;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitInclusiveOrExpression(cmmParser.InclusiveOrExpressionContext ctx) {
        if (ctx.getChildCount() == 1) return visitChildren(ctx);
        visit(ctx.getChild(0));
        String op = ctx.getChild(1).getText();
        visit(ctx.getChild(2));
        Object first = RuntimeVirtualMachine.getrStack().pop();
        Object second = RuntimeVirtualMachine.getrStack().pop();
        int f;
        int s;
        f = GetBool(first);
        s = GetBool(second);
        RuntimeVirtualMachine.getrStack().push((f == 1 || s == 1) ? 1 : 0);
        return null;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitLogicalAndExpression(cmmParser.LogicalAndExpressionContext ctx) {
        if (ctx.getChildCount() == 1) return visitChildren(ctx);
        visit(ctx.getChild(0));
        String op = ctx.getChild(1).getText();
        visit(ctx.getChild(2));
        Object first = RuntimeVirtualMachine.getrStack().pop();
        Object second = RuntimeVirtualMachine.getrStack().pop();
        int f;
        int s;
        f = GetBool(first);
        s = GetBool(second);
        RuntimeVirtualMachine.getrStack().push((f == s) ? 1 : 0);
        return null;
    }

    int GetBool(Object target) {
        if (target.getClass().toString().equals(Var.class.toString())) {
            if (((Var) target).type.equals("Integer"))
                return (((Integer) ((Var) target).value).intValue() == 0) ? 1 : 0;
            if (((Var) target).type.equals("Float"))
                return (((Float) ((Var) target).value).floatValue() == 0f) ? 1 : 0;
            if (((Var) target).type.equals("Double"))
                return (((Double) ((Var) target).value).doubleValue() == 0d) ? 1 : 0;
        }
        if (target.getClass().toString().equals(Integer.class.toString())) return (((Integer)target).intValue() == 0) ? 1 : 0;
        if (target.getClass().toString().equals(Float.class.toString())) return (((Float)target).floatValue() == 0) ? 1 : 0;
        if (target.getClass().toString().equals(Double.class.toString())) return (((Double)target).doubleValue() == 0) ? 1 : 0;
        return 0;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitLogicalOrExpression(cmmParser.LogicalOrExpressionContext ctx) {
        if (ctx.getChildCount() == 1) return visitChildren(ctx);
        return null;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitConditionalExpression(cmmParser.ConditionalExpressionContext ctx) {
        if (ctx.getChildCount() == 1) return visitChildren(ctx);
        return null;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    //赋值表达式
    @Override
    public Object visitAssignmentExpression(cmmParser.AssignmentExpressionContext ctx) {
//        if(ctx.getChildCount()==1) {
//            visit(ctx.conditionalExpression());
//            return null;
//        }
        visit(ctx.unaryExpression());
        Var id = (Var) RuntimeVirtualMachine.getrStack().pop();
        String op = (String) visit(ctx.assignmentOperator());
        visit(ctx.conditionalExpression());
        Object result = RuntimeVirtualMachine.getrStack().pop();
//        if(!result.getClass().toString().equals(id.type))
//        {
//            ErrorOutput.Error("赋值类型不匹配      行号:"+ctx.getStart().getLine());
//        }
//        else
        {
            switch (op) {
                case "=":
                    Assign(id, result);
                    break;
                default:
            }
        }
        return id.value;
    }

    private void Assign(Var tar, Object val) {
        if (val.getClass().toString().equals(Var.class.toString())) {
            val = ((Var) val).value;
        }
        switch (tar.type) {
            case "Integer":
                tar.value = Integer.valueOf(val.toString());
                break;
            case "Float":
                tar.value = Float.valueOf(val.toString());
                break;
            case "Double":
                tar.value = Double.valueOf(val.toString());
                break;
        }
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitConstantExpression(cmmParser.ConstantExpressionContext ctx) {
        visitChildren(ctx);
        return true;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitAssignmentOperator(cmmParser.AssignmentOperatorContext ctx) {
        return ctx.getChild(0).getText();
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitUnaryOperator(cmmParser.UnaryOperatorContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitDeclaration(cmmParser.DeclarationContext ctx) {
        String specifier = (String) visit(ctx.declarationSpecifier());
        ArrayList<ArrayList<Object>> list = (ArrayList<ArrayList<Object>>) visit(ctx.initDeclaratorList());
        SCCTYPE type = null;
        switch (specifier) {
            case "int":
                type = SCCTYPE.INT;
                break;
            case "double":
                type = SCCTYPE.DOUBLE;
                break;
            case "float":
                type = SCCTYPE.FLOAT;
                break;
        }
        for (ArrayList<Object> var : list) {
            int size = var.size();
            String name = (String) var.get(0);
            //如果是数组则应有数组大小
            if (name.contains("-")) {
                String[] arrayDef = name.split("-");
                name = arrayDef[0];
                int arraySize = Integer.valueOf(arrayDef[1]);
                //Object val = null;
                if (size > 1 && arraySize != var.size() - 1) {
                    ErrorOutput.Error("数组定义成员数量不符合定义    行号:" + ctx.getStart().getLine());
                }
                if (size == 1) {
                    RuntimeVirtualMachine.getIdMap().put(name, new Array(type, arraySize));
                    //System.out.println(((Array) RuntimeVirtualMachine.getIdMap().get(name)).array[0]);
                    return null;
                }
                var.remove(0);
                RuntimeVirtualMachine.getIdMap().put(name, new Array(type, arraySize, var));
                //System.out.println((RuntimeVirtualMachine.getIdMap().get(name)).getClass().toString());
                //System.out.println(Array.class.toString());
                //System.out.println(((Array)RuntimeVirtualMachine.getIdMap().get(name)).array[0].value);
                return null;
            }
            //为普通变量的情况
            Object val = null;
            if (size == 2) {
                val = var.get(1);
            }
            RuntimeVirtualMachine.getIdMap().put(name, new Var(type, val));
        }
        return null;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitDeclarationSpecifier(cmmParser.DeclarationSpecifierContext ctx) {
        return ctx.getChild(0).getText();
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitInitDeclaratorList(cmmParser.InitDeclaratorListContext ctx) {
        ArrayList<ArrayList<Object>> list = new ArrayList<ArrayList<Object>>();
        if (ctx.getChildCount() == 1) {
            list.add((ArrayList<Object>) visitChildren(ctx));
        }
        if (ctx.getChildCount() == 3) {
            list.add((ArrayList<Object>) visit(ctx.initDeclarator()));
            list.addAll((ArrayList<ArrayList<Object>>) visit(ctx.initDeclaratorList()));
        }
        return list;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitDeclarator(cmmParser.DeclaratorContext ctx) {

        return visitChildren(ctx);
        //RuntimeVirtualMachine.getIdMap().put(ctx.)
        //return null;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitDirectDeclarator(cmmParser.DirectDeclaratorContext ctx) {
        //声明变量
        if (ctx.getChildCount() == 1) {
            if (RuntimeVirtualMachine.getIdMap().containsKey(ctx.Identifier().getText())) {
                ErrorOutput.Error("重定义的变量:" + ctx.Identifier().getText() + "    行号:" + ctx.Identifier().getSymbol().getLine());
            }
            return ctx.Identifier().getText();
        }
        //声明数组
        if (ctx.getChild(1).getText().equals("[")) {
            String str = "";
            //记得加上多重数组啦
            str += (String) visit(ctx.directDeclarator()) + "-";
            if (ctx.constantExpression() != null) {
                if (ctx.constantExpression().getChildCount() != 1) {
                    ErrorOutput.Error("数组声明参数错误    行号:" + ctx.constantExpression().getStart().getLine());
                    System.exit(0);
                }
                //将操作数入栈
                visit(ctx.constantExpression());
                //取出数组大小参数
                str += RuntimeVirtualMachine.getrStack().pop().toString();
            }
//            if (ctx.constantExpression() != null) {
//                //将操作数入栈
//                visit(ctx.conditionalExpression());
//                //取出数组大小参数
//                str += RuntimeVirtualMachine.getrStack().pop().toString();
//            }
            //str += ctx.
            return str;
        }
        return null;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitIdentifierList(cmmParser.IdentifierListContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitParameterList(cmmParser.ParameterListContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitParameterDeclaration(cmmParser.ParameterDeclarationContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitInitDeclarator(cmmParser.InitDeclaratorContext ctx) {
        ArrayList<Object> list = new ArrayList<Object>();
        if (ctx.getChildCount() == 1) {
            list.add(visitChildren(ctx));
        }
        if (ctx.getChildCount() == 3) {
            list.add(visit(ctx.declarator()));
            list.addAll((ArrayList<Object>) visit(ctx.initializer()));
        }
        return list;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitInitializer(cmmParser.InitializerContext ctx) {
        ArrayList<Object> list = new ArrayList<Object>();
        if (ctx.getChildCount() == 1) {
            visitChildren(ctx);
            list.add(RuntimeVirtualMachine.getrStack().pop());
        }
        if (ctx.getChildCount() == 3) {
            list.addAll((ArrayList<Object>) visit(ctx.initializerList()));
        }
        return list;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitInitializerList(cmmParser.InitializerListContext ctx) {
        ArrayList<Object> list = new ArrayList<Object>();
        if (ctx.getChildCount() == 1) {
            visit(ctx.conditionalExpression());
            list.add(RuntimeVirtualMachine.getrStack().pop());
        }
        if (ctx.getChildCount() == 3) {
            list.addAll((ArrayList<Object>) visit(ctx.initializerList()));
            visit(ctx.conditionalExpression());
            list.add(RuntimeVirtualMachine.getrStack().pop());
        }
        return list;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitStatement(cmmParser.StatementContext ctx) {
        if (ctx.jumpStatement() != null) {
            return visit(ctx.jumpStatement());
        }
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitCompoundStatement(cmmParser.CompoundStatementContext ctx) {
        return visit(ctx.blockItemList());
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitBlockItemList(cmmParser.BlockItemListContext ctx) {
        Object tmp = null;
        if (ctx.getChildCount() == 1) {
            tmp = visit(ctx.blockItem());
            return tmp;
        }
        //遇到break或continue立刻返回
        if ((tmp = visit(ctx.blockItemList())) != null)
            return tmp;
        if ((tmp = visit(ctx.blockItem())) != null)
            return tmp;
        return tmp;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitBlockItem(cmmParser.BlockItemContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitSelectionStatement(cmmParser.SelectionStatementContext ctx) {
        visit(ctx.expression());
        int i;
        Object sentinel = RuntimeVirtualMachine.getrStack().pop();
        if (sentinel.getClass().toString().equals(Var.class.toString())) {
            i = (int) ((Var) sentinel).value;
        } else i = (int) sentinel;
        if (i != 0) {
            visit(ctx.getChild(4));
        } else if (ctx.getChildCount() == 7) {
            visit(ctx.getChild(6));
        }
        return null;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitIterationStatement(cmmParser.IterationStatementContext ctx) {
        Object jumpStatement = null;
        if (ctx.getChild(0).getText().equals("while")) {
            int i;
            do {
                visit(ctx.conditionalExpression());
                Object sentinel = RuntimeVirtualMachine.getrStack().pop();
                if (sentinel.getClass().toString().equals(Var.class.toString())) {
                    i = (int) ((Var) sentinel).value;
                } else i = (int) sentinel;
                if (i != 0) {
                    //检查是否出现跳出语句
                    if ((jumpStatement = visit(ctx.statement())) != null) {
                        if (((String) jumpStatement).equals("break")) return null;
                        continue;
                    }
                } else break;
            } while (true);
            return null;
        }
        if (ctx.getChild(0).getText().equals("for")) {
        }
        return null;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitJumpStatement(cmmParser.JumpStatementContext ctx) {
        return ctx.getChild(0).getText();
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitExpressionStatement(cmmParser.ExpressionStatementContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitExpression(cmmParser.ExpressionContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitCompilationUnit(cmmParser.CompilationUnitContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitTranslationUnit(cmmParser.TranslationUnitContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitExternalDeclaration(cmmParser.ExternalDeclarationContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitFunctionDefinition(cmmParser.FunctionDefinitionContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitDeclarationList(cmmParser.DeclarationListContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitTypeSpecifier(cmmParser.TypeSpecifierContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitTypeName(cmmParser.TypeNameContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitSpecifierQualifierList(cmmParser.SpecifierQualifierListContext ctx) {
        return visitChildren(ctx);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <p>The default implementation returns the result of calling
     * {@link #visitChildren} on {@code ctx}.</p>
     */
    @Override
    public Object visitWriteStatement(cmmParser.WriteStatementContext ctx) {
        visit(ctx.getChild(2));
        Write(RuntimeVirtualMachine.getrStack().pop());
        return visitChildren(ctx);
    }

    private void Write(Object tar) {
        if (tar.getClass().equals(Var.class)) System.out.println(((Var) tar).value);
        if (tar.getClass().equals(Double.class)) System.out.println((Double) tar);
        if (tar.getClass().equals(Float.class)) System.out.println((Float) tar);
        if (tar.getClass().equals(Integer.class)) System.out.println((Integer) tar);
    }
}
